﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using CncConvProg.Model;
using CncConvProg.Model.Tool;
using CncConvProg.Model.Tool.Drill;
using CncConvProg.Model.Tool.LatheTool;
using CncConvProg.Model.Tool.Mill;
using CncConvProg.Model.Tool.Parametro;
using CncConvProg.ViewModel.EditWorkDialog.TreeViewViewModel;
using CncConvProg.ViewModel.MVVM_Library;

namespace CncConvProg.ViewModel.CommonViewModel.ParameterViewModels
{
    public abstract class ToolParameterViewModel : ViewModelBase, IValid, IDataErrorInfo
    {

        public string VelocitaTaglioLabel
        {
            get
            {
                if (_measureUnit == MeasureUnit.Millimeter)
                    return "mt/min";
                return "ft/min";
            }
        }

        public string FeedSyncLabel
        {
            get
            {
                if (_measureUnit == MeasureUnit.Millimeter)
                    return "mm/rev";
                return "inch/rev";
            }
        }

        public string FeedAsyncLabel
        {
            get
            {
                if (_measureUnit == MeasureUnit.Millimeter)
                    return "mm/min";
                return "inch/min";
            }
        }

        public string Unit
        {
            get
            {
                if (_measureUnit == MeasureUnit.Millimeter)
                    return "[mm]";
                return "[Inch]";
            }
        }

        public ParametroUtensile Parametro
        {
            get { return Utensile.ParametroUtensile; }
        }
        private readonly MeasureUnit _measureUnit;

        public Materiale Materiale
        {
            get
            {
                var m = Singleton.Data.GetMateriale(Parametro.MaterialGuid);
                return m;
            }
        }

        public readonly Utensile Utensile;

        protected ToolParameterViewModel(Utensile utensile)
        {
            Utensile = utensile;

            _measureUnit = Parametro.Utensile.Unit;
        }

        public static ToolParameterViewModel GetViewModel(Utensile utensile)
        {
            if (utensile is DrillTool)
                return new ParametroPuntaViewModel(utensile as DrillTool);

            if (utensile is UtensileTornitura)
                return new ParametroUtensileTornituraViewModel(utensile);

            if (utensile is UtensileFilettare)
                return new ParametroUtensileTornituraFilettaturaViewModel(utensile);

            if (utensile is UtensileScanalatura)
                return new ParametroUtensileTornituraScanalaturaViewModel(utensile);

            if (utensile is FresaCandela)
                return new ParametroFresaCandelaViewModel(utensile as FresaCandela);

            if (utensile is FresaFilettare)
                return new ParametroFresaFilettareViewModel(utensile as FresaFilettare);

            if (utensile is FresaSpianare)
                return new ParametroFresaSpianareViewModel(utensile as FresaSpianare);

            throw new NotImplementedException();
        }

        public event EventHandler OnUpdated;

        /// <summary>
        /// Evento chiamato quando modifico proprieta ( onPropertychanged e quando modifico userinputviewmodel)..
        /// </summary>
        /// <param name="caller"></param>
        protected void RequestUpdate(ViewModelBase caller)
        {
            _modified = true;

            var handler = OnUpdated;
            if (handler != null)
                handler(caller, EventArgs.Empty);
        }

        protected override void OnPropertyChanged(string propertyName)
        {

            if (propertyName != "IsValid")
            {
                // richiedi aggiornamento parent
                RequestUpdate(this);
                OnPropertyChanged("IsValid");
            }

            base.OnPropertyChanged(propertyName);
        }


        public double UsuraEuroMin
        {
            get
            {
                return Parametro.UsuraEuroMin;
            }
            set
            {
                Parametro.UsuraEuroMin = value;
                OnPropertyChanged("UsuraEuroMin");
            }
        }

        public double TempoVitaUtensile
        {
            get
            {
                return Parametro.TempoVitaUtensile;
            }
            set
            {
                if (Parametro.TempoVitaUtensile == value) return;
                Parametro.TempoVitaUtensile = value;
                OnPropertyChanged("TempoVitaUtensile");
                if (value > 0)
                    MetriVitaUtensile = 0;
                UpdateUsuraUtensile();
            }
        }

        public double MetriVitaUtensile
        {
            get
            {
                return Parametro.MetriVitaUtensile;
            }
            set
            {
                if (Parametro.MetriVitaUtensile == value) return;
                Parametro.MetriVitaUtensile = value;
                OnPropertyChanged("MetriVitaUtensile");
                if (value > 0)
                    TempoVitaUtensile = 0;
                UpdateUsuraUtensile();

            }
        }

        public double CostoUtensile
        {
            get
            {
                return Parametro.CostoUtensile;
            }
            set
            {
                if (Parametro.CostoUtensile == value) return;
                Parametro.CostoUtensile = value;
                OnPropertyChanged("CostoUtensile");
                UpdateUsuraUtensile();
            }
        }
        RelayCommand _updateCostoUnitario;

        private void UpdateUsuraUtensile()
        {
            UsuraEuroMin = Parametro.CalcolateUnitToolCost();
        }

        public ICommand UpdateUsuraUtensileCmd
        {
            get
            {
                return _updateCostoUnitario ?? (_updateCostoUnitario = new RelayCommand(param => UpdateUsuraUtensile(),
                                                                                        param => true));
            }
        }


        #region IDataErrorInfo Members

        string IDataErrorInfo.Error { get { return null; } }

        string IDataErrorInfo.this[string propertyName]
        {
            get { return GetValidationError(propertyName); }
        }

        private bool _isValid;
        private bool _modified = true;
        /// <summary>
        /// Returns true if this object has no validation errors.
        /// </summary>
        public bool IsValid
        {
            get
            {
                if (_modified)
                {
                    var isValid = ValidatedProperties.All(property => GetValidationError(property) == null);

                    _isValid = isValid;

                    _modified = false;
                }
                return _isValid;
            }
        }

        protected abstract string[] ValidatedProperties { get; }

        protected abstract string GetValidationError(string propertyName);

        #endregion
    }
}
